package m.html.collect;

import m.common.model.DictionaryModel;
import m.common.model.Model;
import m.html.element.*;
import m.html.element.attr.Align;
import m.html.element.other.DisplayItem;
import m.html.element.other.IElement;
import m.html.list.*;
import m.html.util.VueListColumn;
import m.html.util.VueListUtil;
import m.system.exception.MException;
import m.system.util.GenerateID;
import m.system.util.ObjectUtil;
import m.system.util.StringUtil;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class CollectColumn implements VueListColumn {

	private CollectColumnType type;
	private String title;//标题
	private String[] groupTitle;//标题组
	private String field;//sql字段
	private String fieldAs;//别名
	private int width;//宽
	private Align fixed;//浮动对齐
	private Boolean sort=false;//排序
	private ListSortOrder sortOrder=ListSortOrder.NONE;//默认排序
	private ListCount countType=ListCount.NONE;
	private Boolean filter=false;//过滤
	private SearchType filterType=SearchType.HIDDEN_LIKE;//过滤类型
	private String dateFormat;//yyyy-MM-dd HH:mm:ss:SSS
	private String numberFormat;//#,##0.00
	private Align align;//对齐
	private List<DisplayItem> disItems;
	private String dictType;
	private boolean dictTree=false;
	private final List<String> styles;
	private Integer lineClamp=2;
	private ListEvent linkEvent;//link列使用
	private Boolean show=true;
	private Boolean subtotal=false;
	private Boolean copy=false;

	public CollectColumn(String title,String field) throws MException {
		this(CollectColumnType.NORMAL,title, field,100);
	}
	public CollectColumn(String title,String field,int width) throws MException {
		this(CollectColumnType.NORMAL,title,field,width);
	}
	public CollectColumn(CollectColumnType type,String title,String field) throws MException {
		this(type,title,field,100);
	}
	public CollectColumn(CollectColumnType type,String title,String field,int width) throws MException {
		if(StringUtil.isSpace(field)) field="tmp_"+GenerateID.tempKey();
		this.setField(field);
		this.title=title;
		this.type=type;
		this.setWidth(width);
		this.align=Align.LEFT;
		this.elementList= new ArrayList<>();
		this.fixed=Align.NONE;
		this.disItems= new ArrayList<>();
		this.styles= new ArrayList<>();
	}
	private final Set<String> paramFields= new HashSet<>();
	private CollectColumn addParamField(String field) {
		if(StringUtil.isSpace(field)) return this;
		if(field.indexOf("tmp_")==0) return this;
		this.paramFields.add(field);
		return this;
	}
	/**
	 * 获取参数所需的字段
	 * 
	 */
	public Set<String> getParamFields() {
		Set<String> pf = new HashSet<>(this.paramFields);
		for(IListElement ele : elementList) {
			pf.addAll(ele.getParamFields());
		}
		if(type==CollectColumnType.LINK) {
			if(null!=linkEvent) {
				pf.addAll(linkEvent.getParamFields());
			}
		}
		return pf;
	}
	/**
	 * 子元素列表
	 */
	private final List<IListElement> elementList;
	/**
	 * 添加子元素
	 *  element
	 * 
	 */
	public CollectColumn addElement(IListElement element) {
		this.elementList.add(element);
		return this;
	}
	public CollectColumn setTitle(String title) {
		this.title = title;
		return this;
	}
	public CollectColumn setField(String field) throws MException {
		if(field.indexOf("tmp_")==0) {
			this.field=field;
			this.fieldAs=field;
			return this;
		}
		if(field.lastIndexOf(" ")<0) throw new MException(this.getClass(), "field设置错误");
		this.addParamField(field);
		String n=field.substring(field.lastIndexOf(" ")+1);
		field=field.substring(0,field.lastIndexOf(" "));
		this.field = field;
		this.fieldAs=n;//别名
		return this;
	}
	public CollectColumn setWidth(int width) {
		this.width=width;
		return this;
	}
	public CollectColumn setFixed(Align fixed) {
		this.fixed = fixed;
		return this;
	}
	public CollectColumn setType(CollectColumnType type) {
		this.type = type;
		return this;
	}
	/**
	 * 设置是否排序
	 *  sort
	 * 
	 */
	public CollectColumn setSort(Boolean sort) {
		this.sort = sort;
		return this;
	}
	/**
	 * 设置默认排序 设置后开启排序
	 *  order
	 * 
	 */
	public CollectColumn setSort(ListSortOrder order) {
		this.sortOrder=order;
		this.sort = true;
		return this;
	}
	/**
	 * 设置合计类型
	 *  countType
	 * 
	 */
	public CollectColumn setCount(ListCount countType) {
		this.countType=countType;
		return this;
	}
	public ListCount getCount() {
		return this.countType;
	}
	public String getDictType() {
		return dictType;
	}

	/**
	 * 字典
	 */
	public CollectColumn setDictType(String dictType) {
		this.dictType = dictType;
		return this;
	}

	/**
	 * 字典
	 */
	public <T extends DictionaryModel> CollectColumn setDictType(Class<T> clazz){
		return setDictType(clazz.getName());
	}
	/**
	 * 字典
	 */
	public <T extends DictionaryModel> CollectColumn setDictType(Class<T> clazz,String key){
		return setDictType(clazz.getName()+":"+key);
	}
	/**
	 * 字典
	 */
	public <T extends Model> CollectColumn setDictOption(Class<T> clazz, String field){
		return setDictType(clazz.getName()+"!"+field);
	}
	public CollectColumn setDictTree(boolean dictTree){
		this.dictTree=dictTree;
		return this;
	}

	public boolean isDictTree() {
		return dictTree;
	}
	public CollectColumn setFilter(Boolean filter) {
		this.filter = filter;
		return this;
	}
	public CollectColumn setFilter(SearchType type) {
		this.filter=true;
		this.filterType=type;
		return this;
	}
	public CollectColumn setShow(boolean show) {
		this.show=show;
		return this;
	}
	public CollectColumn setCopy(boolean copy){
		this.copy=copy;
		return this;
	}

	/**
	 * 设置小计列 只能设置普通列
	 */
	public CollectColumn setSubtotal(Boolean subtotal) {
		this.subtotal = subtotal;
		return this;
	}
	public CollectColumn setDateFormat(String dateFormat) {
		this.dateFormat = dateFormat;
		return this;
	}
	public CollectColumn setNumberFormat(String numberFormat) {
		this.numberFormat = numberFormat;
		return this;
	}
	public CollectColumn setAlign(Align align) {
		this.align=align;
		return this;
	}
	public CollectColumn setLineClamp(Integer lineClamp) {
		this.lineClamp = lineClamp;
		return this;
	}
	/**
	 * 添加显示项
	 *  item
	 * 
	 */
	public CollectColumn addDisItem(DisplayItem item) {
		this.disItems.add(item);
		return this;
	}
	/**
	 * 添加显示项 单数为值,双数为名称
	 *  vs
	 * 
	 */
	public CollectColumn addDisItem(String... vs) {
		this.disItems.addAll(DisplayItem.to(vs));
		return this;
	}
	/**
	 * 设置显示项  可通过ItemsQuery,DisplayItem类实现
	 *  list
	 * 
	 */
	public CollectColumn setDisItems(List<DisplayItem> list) {
		this.disItems=list;
		return this;
	} 
	/**
	 * 单元格样式    {text, record, index} 当前列字段，行记录，行
	 *  test    例如:text=='1'
	 *  style  样式 例如: color:#f00;
	 * 
	 */
	public CollectColumn setStyle(String test,String style) {
		this.styles.add("("+test+"?'"+style+"':'')");
		return this;
	}
	public CollectColumn setLinkEvent(ListEvent linkEvent) {
		this.linkEvent = linkEvent;
		return this;
	}
	public CollectColumn setGroupTitle(String... groupTitle) {
		this.groupTitle=groupTitle;
		return this;
	}
	public String getNumberFormat() {
		return StringUtil.noSpace(this.numberFormat);
	}
	public String getDateFormat() {
		return StringUtil.noSpace(this.dateFormat);
	}
	private void setFalse() {
		if(this.field.indexOf("tmp_")==0) {
			this.filter=false;
			this.sort=false;
		}
	}
	public boolean isFalse() {
		return this.field.indexOf("tmp_")==0;
	}
	public String toJsonString() {
		StringBuilder sb=new StringBuilder();
		sb.append("{")
		.append("\"title\":\"").append(StringUtil.conver2JS(this.title)).append("\",");
		sb.append("\"width\":").append(this.width).append(",")
		.append("\"resizable\":true,");
		if(this.fixed!=Align.NONE) sb.append("\"fixed\":\"").append(this.fixed).append("\",");
		if(this.align!=Align.NONE) sb.append("\"align\":\"").append(this.align).append("\",");
		if(this.sort) sb.append("\"sorter\":\"").append(this.sort).append("\",");
		sb.append("\"key\":\"").append(this.fieldAs).append("\",");
		try {
			sb.append("\"dataIndex\":").append(ObjectUtil.toString(this.fieldAs.split("\\."))).append(",");
		}catch(Exception ignored) {}
		sb.append("\"slots\": {");
		if(this.filter) {
			sb.append("	\"filterDropdown\":\"").append(this.fieldAs.replaceAll("\\.", "_")).append("fd\",")
			.append("	\"filterIcon\":\"filter-icon\",");
		}
		sb.append("		\"customRender\":\"").append(this.fieldAs.replaceAll("\\.", "_")).append("\"");
		sb.append("  }")
		.append("}");
		return sb.toString();
	}
	public String toExtendString() {
		setFalse();
		StringBuilder sb=new StringBuilder();
		Element temp1=Element.tag("template").A("#"+this.fieldAs.replaceAll("\\.", "_"),"{text, record, index}");
		StringBuilder style= new StringBuilder("''");
		for(String st : this.styles) style.append("+").append(st);
		Element tmp=Element.tag("div").A(":style", style.toString())
			.A("class", "td-wrap").A("style", "-webkit-line-clamp:"+this.lineClamp);
		if(this.elementList.size()==0) {
			if(this.type==CollectColumnType.INDEX) {//序号列
				tmp.A("style","white-space:nowrap;").E(new Text("{{(page.index-1)*page.num+index+1}}"));
			}else if(this.type==CollectColumnType.LINK) {
				Element a=Element.tag("a-typography-link").E(VueListUtil.toText(this.dateFormat,this.numberFormat,this.dictType,this.disItems,false));
				if(null!=linkEvent) a.setExtend(linkEvent.toExtendString());
				tmp.E(a);
			}else{
				tmp.E(VueListUtil.toText(this.dateFormat,this.numberFormat,this.dictType,this.disItems,this.copy));
			}
		}else {//文本数字日期字典类型
			tmp.E(this.elementList);
		}
		temp1.E(tmp);
		sb.append(temp1);
		//自定义搜索
		if(this.filter) {
			Element temp2=Element.tag("template").A("#"+this.fieldAs.replaceAll("\\.", "_")+"fd","{ setSelectedKeys, selectedKeys, confirm, clearFilters, column }");
			Element qc=Element.tag("div").A("style","padding:12px");
			qc.E(Element.tag("a-divider").A("orientation","left").A("style","width:150px;margin:0 0 10px;").E(new Text("{{column.title}}") ));
			if(!StringUtil.isSpace(this.dictType)) {
				if(this.dictTree){
					qc.E(
						Element.tag("div").A("style","padding:0 0 10px;")
						.E(Element.tag("a-tree-select").A("v-model:value","inputParams[column.key]")
							.A(":tree-data","dictTreeOptions('"+this.dictType+"')").A("multiple")
							.A(":filterTreeNode","treeSelectFilter").A("style","width:230px;").A(":showArrow","true")
							.A(":getPopupContainer", "selectPopup")
						)
					);
				}else{
					qc.E(
						Element.tag("div").A("style","padding:0 0 10px;")
						.E(Element.tag("a-select").A("v-model:value","inputParams[column.key]")
							.A(":options","dictOptions('"+this.dictType+"')").A("mode","multiple")
							.A(":filter-option","selectFilter").A("style","width:230px;").A(":showArrow","true")
							.A(":getPopupContainer", "selectPopup")
						)
					);
				}
			}else if(this.disItems.size()>10) {
				List<IElement> rs= new ArrayList<>();
				for(DisplayItem di : this.disItems) {
					rs.add(
						Element.tag("a-select-option").A("key",di.getValue()).A("value",di.getValue()).E(new Text(di.getTitle()))
					);
				}
				qc.E(
					Element.tag("div").A("style","padding:0 0 10px;")
					.E(Element.tag("a-select").A("v-model:value","inputParams[column.key]").A("mode","multiple")
						.A(":filter-option","selectFilter").A("style","width:230px;").A(":showArrow","true")
						.A(":getPopupContainer", "selectPopup")
						.E(rs))
				);
			}else if(this.disItems.size()>0) {
				List<IElement> rs= new ArrayList<>();
				for(DisplayItem di : this.disItems) {
					rs.add(
						Element.tag("div").A("style","padding:0 5px 10px;")
						.E(Element.tag("a-checkbox").A("value",di.getValue()).E(new Text(di.getTitle())))
					);
				}
				qc.E(
					Element.tag("div")
					.E(Element.tag("a-checkbox-group").A("v-model:value","inputParams[column.key]")
						.E(rs))
				);
			}else if(this.filterType==SearchType.NUMBER_RANGE||this.filterType==SearchType.HIDDEN_NUMBER_RANGE){
				qc.E(
					Element.tag("div").A("style","padding:0 0 10px;")
					.E(
						new InputNumber("inputParams[column.key+'_down']")
					)
					.E(new Text(" ~ "))
					.E(
						new InputNumber("inputParams[column.key+'_up']")
					)
				);
			}else if(this.filterType==SearchType.DATE_RANGE||this.filterType==SearchType.HIDDEN_DATE_RANGE
					||this.filterType==SearchType.DATETIME_RANGE||this.filterType==SearchType.HIDDEN_DATETIME_RANGE) {
				boolean flag=this.filterType==SearchType.DATETIME_RANGE||this.filterType==SearchType.HIDDEN_DATETIME_RANGE;
				qc.E(
					Element.tag("div").A("style","padding:0 0 10px;")
					.E(
						new DatePicker("inputParams[column.key+'_down']",flag).A("style", flag?"width:170px":"width:130px")
					)
					.E(new Text(" ~ "))
					.E(
						new DatePicker("inputParams[column.key+'_up']",flag).A("style", flag?"width:170px":"width:130px")
					)
				);
			}else{
				qc.E(
					Element.tag("a-input").A("ref","searchInput").A(":placeholder","'搜索'+column.title")
					.A("v-model:value","inputParams[column.key]").A("style","width: 200px; margin-bottom: 8px; display: block")
					.A("@pressEnter","clearFilters();filterHandle(selectedKeys, column);")
				);
			}
			qc.E(
				Element.tag("div").A("style","text-align:right;")
				.E(
					Element.tag("a-button").A("type","primary").A("size","small").A("style","width: 75px; margin-right: 12px")
					.A("@click","clearFilters();filterHandle(selectedKeys, column);")
					.E(new Text("<template #icon>"+new Icon("icon-icon-33")+"</template>查询"))
				)
				.E(
					Element.tag("a-button").A("size","small").A("style","width: 75px")
					.A("@click","clearFilters();resetHandle(column);")
					.E(new Text("重置"))
				)
			);
			temp2.E(qc);
			sb.append(temp2);
			// end 自定义搜索
		}
		return sb.toString();
	}
	public String getField() {
		return field;
	}
	public String getFieldAs() {
		return fieldAs;
	}
	public String getType() {
		return type.toString();
	}
	public String getTitle() {
		return title;
	}
	public Boolean getFilter() {
		return filter;
	}
	public SearchType getFilterType() {
		return filterType;
	}
	public List<DisplayItem> getDisItems(){
		return this.disItems;
	}
	public ListSortOrder getSortOrder() {
		return sortOrder;
	}
	public int getWidth() {
		return width;
	}
	public Align getAlign() {
		return align;
	}
	public String[] getGroupTitle() {
		return groupTitle;
	}
	public Align getFixed() {
		return fixed;
	}
	public Boolean getShow() {
		return show;
	}

	public Boolean getSubtotal() {
		return subtotal;
	}

}
